package com.sxkj.service.sys;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sxkj.common.response.ResponseResult;
import com.sxkj.common.utils.Md5Util;
import com.sxkj.common.utils.StringUtils;
import com.sxkj.entity.entity.sys.Menu;
import com.sxkj.entity.entity.sys.User;
import com.sxkj.entity.entity.sys.UserRole;
import com.sxkj.entity.mapper.sys.UserMapper;
import com.sxkj.common.utils.JwtTokenUtil;
import com.sxkj.service.base.BaseService;
import com.sxkj.service.redis.RedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @author: daixiaowei
 * @date: 2019年12月09日 16:21
 * @Description: 用户相关接口
 */
@Service
public class UserService extends BaseService<UserMapper,User> {
    private static final Logger LOGGER = LoggerFactory.getLogger(UserService.class);
    @Autowired
    private MenuService menuService;
    @Autowired
    private UserRoleService userRoleService;
//    @Autowired
//    private UserMapper userMapper;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Value("${jwt.tokenHeader}")
    private String tokenHeader;

    @Value("${jwt.authHeader}")
    private String authHeader;
    @Autowired
    private RedisService redisService;
    /**
     *
     * @title: getUserByUsername
     * @author: daixiaowei
     * @date: 2019年12月10日 下午 03:06:59
     * @description: 通过用户名查询User及其权限
     * @param: userName
     * @return:
     */
    public UserDetails getUserByUsername(String userName) {
        List<User> userList = baseMapper.selectByLoginName(userName);
        if (userList != null && userList.size() > 0) {
            User user= userList.get(0);
            List<Menu> permissionList = menuService.getPermissionList(user.getId());
            return new AdminUserDetails(user,permissionList);
        }
        throw new UsernameNotFoundException("用户名或密码错误");
    }

    /**
     *
     * @title: register
     * @author: daixiaowei
     * @date: 2019年12月09日 下午 05:14:19
     * @description: 用户注册
     * @param:
     * @return:
     */
    public User register(User umsAdminParam) {
        User umsAdmin = new User();
        BeanUtils.copyProperties(umsAdminParam, umsAdmin);
        //查询是否有相同用户名的用户
        //将密码进行加密操作
        String encodePassword = passwordEncoder.encode(umsAdmin.getPassword());
        umsAdmin.setPassword(encodePassword);
        //UserMapper.insert(umsAdmin);
        return umsAdmin;
    }

    /**
     *
     * @title: login
     * @author: daixiaowei
     * @date: 2019年12月09日 下午 05:12:03
     * @description: 登陆获取token 和权限
     * @param: username password
     * @return:
     */
    public ResponseResult login(User user, HttpServletRequest request, HttpServletResponse response) {
        try {
            UserDetails userDetails = getUserByUsername(user.getUserName());
            if (passwordEncoder.matches(user.getPassword().trim(), userDetails.getPassword())) {
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(authentication);
                String token = jwtTokenUtil.generateToken(userDetails);

                response.setHeader(this.authHeader,token);
                token = Md5Util.md5(token,"sxkj");
                response.setHeader(this.tokenHeader,token);
                Map<String, Object> map = new HashMap<>();
                map.put("user", userDetails);
                map.put("menuTreeList",menuService.formatMenuTreeList(((AdminUserDetails) userDetails).permissionList));
                map.put("menuTree",menuService.formatMenuTree());
                redisService.set(token,"0");
                LOGGER.info(redisService.get(token));
                return ResponseResult.success(map);
            }

        } catch (AuthenticationException e) {
            LOGGER.warn("登录异常:{}", e.getMessage());
        }
        return ResponseResult.failure("用户名或密码错误");
    }

    /**
     *
     * @title: refreshToken
     * @author: daixiaowei
     * @date: 2019年12月13日 上午 09:43:25
     * @description: 手动刷新token接口
     * @param: token
     * @return:
     */
    public String refreshToken(String token) {
        return jwtTokenUtil.refreshHeadToken(token);
    }

    /**
     *
     * @title: searchListPage
     * @author: daixiaowei
     * @date: 2019年12月19日 上午 11:54:38
     * @description: 查询用户列表
     * @param: nickName pageSize pageNum
     * @return:
     */
    public PageInfo searchListPage(String nickName, Integer pageSize, Integer pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        return new PageInfo(baseMapper.searchListPage(nickName));
    }

    /**
     *
     * @title: searchUniqueByName
     * @author: daixiaowei
     * @date: 2019年12月19日 下午 02:39:06
     * @description: 查询登录名是否重复
     * @param: userName
     * @return: Boolean
     */
    public Boolean searchUniqueByName(String userName) {
        List<User> list= baseMapper.selectByLoginName(userName);
        if (list!=null&&list.size()>0) {
            return true;
        }
        return false;
    }

    /**
     *
     * @title: userAdd
     * @author: daixiaowei
     * @date: 2019年12月19日 下午 03:10:13
     * @description: 用户添加
     * @param: umsAdminParam
     * @return:
     */
    public User userAdd(User user) {
        //将密码进行加密操作
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.preInsert();
        JSONArray ja=JSON.parseArray(user.getRoleIds());
        userRoleInsert(user,ja);
        baseMapper.insert(user);
        return user;
    }

    /**
     *
     * @title: userRoleInsert
     * @author: daixiaowei
     * @date: 2019年12月20日 上午 11:45:11
     * @description: 关联表插入
     * @param: umsAdmin ja
     * @return:
     */
    private void userRoleInsert(User user,JSONArray ja) {
        for (int i=0;i<ja.size();i++){
            UserRole userRole = new UserRole();
            userRole.setRoleId(ja.get(i).toString());
            userRole.setRoleName(user.getRoleNames().split(",")[i]);
            userRole.setUserId(user.getId());
            userRoleService.insert(userRole);
        }
    }

    /**
     *
     * @title: userUpdate
     * @author: daixiaowei
     * @date: 2019年12月20日 上午 10:48:38
     * @description: 用户修改
     * @param: user
     * @return:
     */
    public User userUpdate(User user) {
        User umsAdmin = baseMapper.selectByPrimaryKey(user.getId());
        if (StringUtils.isNotEmpty(user.getNickName())) {
            umsAdmin.setNickName(user.getNickName());
        }
        if (StringUtils.isNotEmpty(user.getEmail())) {
            umsAdmin.setEmail(user.getEmail());
        }
        if (StringUtils.isNotEmpty(user.getPhone())) {
            umsAdmin.setPhone(user.getPhone());
        }
        umsAdmin.setDisabled(user.getDisabled());
        umsAdmin.preUpdate();
        JSONArray ja=JSON.parseArray(user.getRoleIds());
        if (StringUtils.isNotEmpty(user.getId())) {
            userRoleService.deleteByUserId(user.getId());
            userRoleInsert(user,ja);
        }
        baseMapper.update(umsAdmin);
        return umsAdmin;
    }

    /**
     *
     * @title: deleteByUserId
     * @author: daixiaowei
     * @date: 2019年12月20日 下午 01:29:52
     * @description: 删除用户及关联表
     * @param: id
     * @return:
     */
    public void deleteByUserId(String id) {
        userRoleService.deleteByUserId(id);
        baseMapper.deleteById(id);
    }

    /**
     *
     * @title: restPassword
     * @author: daixiaowei
     * @date: 2019年12月20日 下午 01:46:03
     * @description: 重置密码
     * @param: id
     * @return:
     */
    public void restPassword(String id) {
        User umsAdmin = baseMapper.selectByPrimaryKey(id);
        umsAdmin.setPassword(passwordEncoder.encode("0"));
        baseMapper.update(umsAdmin);
    }
}


